package reward

import (
	"strconv"

	"github.com/golang/protobuf/proto"
	"hundsun.com/hsl/hschain/common/config"
	"hundsun.com/hsl/hschain/common/types"
	"hundsun.com/hsl/hschain/common/util/pb"
	"hundsun.com/hsl/hschain/contract"
	ecom "hundsun.com/hsl/hschain/executor/common"
	pbcommon "hundsun.com/hsl/hschain/protos/common"
	"hundsun.com/hsl/hschain/protos/execute"
	"hundsun.com/hsl/hschain/protos/ledger"
	"hundsun.com/hsl/hschain/store/extend/account"
)

// Reg 注册执行器名称
func Reg(cfg *config.PluginConfig) {
	height := uint64(0)
	if cfg != nil {
		if v, ok := cfg.Parameters["height"]; ok {
			h, err := strconv.ParseInt(v, 10, 64)
			if err == nil && h > 0 {
				height = uint64(h)
			}
		}
	}
	contract.Register(NativeReward, newNativeReward, false, true, height)
}

type nativeReward struct{}

func newNativeReward() contract.Contract {
	return &nativeReward{}
}

func (c *nativeReward) Init() {}

func (c *nativeReward) Run(ctx *ecom.ExecContent, gtx *execute.GroupedTransaction) (*execute.GroupedTransaction, error) {
	tx := gtx.GetTx()

	// 校验mining交易的发送方是否为创世块中的Miner
	from := tx.GetFrom()

	// reward 额度检查
	reward := tx.GetValue()
	genesisPayload := pb.GetGenesisTransactionPayload()
	if reward != genesisPayload.GetReward() {
		gtx.TxExecRst.Receipt.TxStatus = ledger.TransactionReceipt_PARAMETER_NOT_VALID
		return gtx, nil
	}

	acc := account.NewAccountDB(ctx)
	fromAccount, _ := acc.GetAccount(from)
	if fromAccount == nil {
		//不存在则创建
		fromAccount = &pbcommon.Account{InternalAddress: from,
			Balance: reward,
			Type:    pbcommon.Account_USER}
	} else {
		fromBalance := fromAccount.GetBalance()
		fromBalance = fromBalance + reward
		fromAccount.Balance = fromBalance
	}
	kv, _ := account.KV(fromAccount)
	gtx.TxExecRst.Kvs = append(gtx.TxExecRst.Kvs, kv)
	gtx.TxExecRst.Receipt.Logs = append(gtx.TxExecRst.Receipt.Logs, &ledger.Log{Ty: types.TyLogTransfer, Data: kv.Value})
	ctx.GetStateHandle().SetLocal(kv.Key, kv.Value)

	return gtx, nil
}

func (c *nativeReward) Rollback(ctx *ecom.ExecContent, gtx *execute.GroupedTransaction) (*execute.GroupedTransaction, error) {
	panic("implement me")
}

func (c *nativeReward) Query(ctx *ecom.ExecContent, funcName string, param []byte) (proto.Message, error) {
	panic("implement me")
}
